Skip to content

Fix/payment settlement delivery - #112

Open
1amKhush wants to merge 14 commits into
ContextVM:masterfrom
1amKhush:fix/payment-settlement-delivery
Open

1amKhush wants to merge 14 commits into
ContextVM:masterfrom
1amKhush:fix/payment-settlement-delivery

Conversation

@1amKhush

@1amKhush 1amKhush commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Depends on #108 and #110. Related: #111.

Summary

Recognize settlement despite missed notifications and retry retained paid results after publication failures without another payment or handler execution.

  • Bound adapter operations with cancellation/deadlines, clean up owned resources, and use authenticated settlement lookup when notifications are unreliable.
  • Restore response routes/session state after ordinary and oversized publication failures; preserve caller response IDs and stream reservation ownership.
  • Record settlement, outcomes, and publication progress through the injected PaymentStateStore; fence reconciliation and publication by generation/ownership.
  • Merge the latest fix(payments): harden client payment attempts and retries #108/Feat/payment state durability #110 compatibility fixes and remove PostgreSQL source, migrations, dependencies, exports, SQL-only tests, and database CI setup.
  • Keep runtime qualification and replace database-only E2E coverage with 21 always-run injected-store cases across cleartext, persistent encryption, and ephemeral encryption.

Storage and recovery contract

The SDK bundles only in-memory storage and adds no storage dependency. Recreating a transport can recover results while the same application-owned store remains alive. Process restart or cross-host recovery requires a persistent implementation supplied and managed by the application. The SDK does not initialize/close custom backends or fall back to fresh memory on their errors.

Default-store lifetime limits are tested explicitly. A fresh memory store cannot recover an earlier result. No distributed-backend or process-crash durability guarantee is claimed for the bundled store.

Validation

  • Full concurrent suite without a database: 836 passed, 5 live-wallet tests skipped, 0 failures.
  • Injected-store E2E cases cover ordinary/start/chunk/end publication failure, lost result/publication commit acknowledgements, transport recreation, serialized records, and signed/encrypted replay. Assertions count invoices, approvals, verification, handler execution, terminal publication, and client completion separately.
  • Typecheck, lint, clean ESM build, public exports, frozen lockfile, Node 18.20.8 smoke, and browser entrypoint checks passed.
  • Package dry run contains no PostgreSQL files or local work notes. Tree-shaken transport consumers from root/transport entrypoints include no payment storage, adapters, or recovery implementation.

Copilot AI balanced review requested due to automatic review settings October 21, 2026 06:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

hzrd149 pushed a commit to hzrd149/contextvm-sdk that referenced this pull request Nov 11, 2026
…on-positive TTLs

Bundles the two remaining verified findings from the rs-sdk ContextVM#111/ContextVM#112
review round:

Writer leak on the gating drop path. Every inbound tools/call with a
progressToken reserves an OpenStreamWriter before middleware runs. A
request dropped by middleware (explicit gating -32042/-32043/-32000,
transparent payment_rejected, capacity refusal, or any custom gating)
never produces the normal-path response that is the only reaper for
never-started writers, so the reservation (writer + closures + abort
controller + metadata) leaked until transport teardown — one per gated
streaming invocation on exactly the path a busy paid API hammers. A
throwing middleware chain leaked the correlation route too. Fix:
cleanupDroppedRequest is now the single owner of per-request state and
releases the writer alongside the route; the chain-error path runs the
same cleanup; the release logic is extracted as
ServerOpenStreamFactory.releaseUnusedWriter and reused by
deferIfStreamActive's never-started branch.

Non-positive TTLs. paymentTtlMs: 0 (both lifecycles) and invoice
ttl: 0 (explicit gating grant) birth-expired the pending/grant entry
while the invoice stayed payable, disarming the redelivery dedup
(CEP-8). Both now fall back to the default window, mirroring the guard
getVerificationTimeoutMs already applied.

Also documents the run-to-completion atomicity assumption of
claim()+trySetPending() for porters (insight from the rs port).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants